package com.qtrue.exer;

/**
 * @Package: com.qtrue.exer
 * @ClassName: AccountTest
 * @Author: xiaoBao
 * @CreateTime: 2022-05-09 18:52
 * @Description:线程同步机制的课后练习
 *  银行有一个账户。
 *      有两个储户分别向同一个账户存3000元，每次存1000元，存3次。每次存完打印账户余额。
 *
 *  分析：
 *      1. 是否是多线程问题？ 是，两个储户为两个线程。
 *      2. 是否有共享数据？ 有，账户（或账户余额）。
 *      3. 是否有线程安全问题？ 有（有共享数据并且有多个线程操作的情况下就会有线程安全问题）。
 *      4. 需要考虑如何解决线程安全问题？ 同步机制（有三种方式）。
 *
 */
public class AccountTest {
    public static void main(String[] args) {
        // 实例化账户的对象
        Account account = new Account();
        // 实例化线程类的对象，传入参数声明两个线程使用的是同一个账户。
        Costmer cost01 = new Costmer(account);
        Costmer cost02 = new Costmer(account);

        // 设置线程名称
        cost01.setName("储户甲");
        cost02.setName("储户乙");

        // 启动线程
        cost01.start();
        cost02.start();
    }
}

// 储户
class Costmer extends Thread {
    // 因为多个储户是向一个账户存钱。引入Account账户类。
    // 这里的对象属性也可以使用static来修饰，这样就不需要声明构造器在当前类实例化时传入参数了。
    private Account acct;

    // 声明一个构造器，在线程创建时传入同一个账户的对象。
    public Costmer(Account acct) {
        this.acct = acct;
    }

    @Override
    public void run() {

        for(int i = 0;i<3;i++){
            acct.deposit(1000);
        }

    }
}

// 账户
class Account {
    private double balance = 0; //账户余额

    public synchronized void deposit(double money){
        if(money > 0){
            balance += money;

            try {
                Thread.sleep(1000); // 线程挂起
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println(Thread.currentThread().getName() + "存钱成功：余额为：" + balance);
        }
    }
}